package com.xzit.rental.utils;

import com.xzit.rental.entity.Dept;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * deptList：代表系统中所有部门信息的列表
 * pid：表示父部门的编号（或者叫标识）初始调用时通常传入代表根节点的父部门编号（例如约定根节点的父部门编号为0或者-1等）
 */
public class DeptTreeUtils {
    public static List<Dept> buildDeptTree(List<Dept> deptList, int pid) {

        // 1、创建存放部门树的列表：存放最终构建好的部门树结构中的各个部门节点
        List<Dept> deptTree = new ArrayList<>();

        //  2、处理部门列表并筛选出子部门
        // 引入的Optional类来优雅地处理可能为null的deptList参数，ofNullable方法会将传入的参数包装成Optional对象，
        // 如果传入的deptList为null，那么就通过orElse方法返回一个新的空的ArrayList，避免出现空指针异常。
        Optional.ofNullable(deptList).orElse(new ArrayList<>())
                // 对处理后的部门列表（非null的原始列表或者空的ArrayList）调用stream方法创建一个流，以便进行后续的流式操作
                .stream()
                // 使用filter方法对流中的元素（也就是部门对象）进行筛选，筛选条件是部门对象不为null
                // 并且该部门对象的pid（父部门编号）属性等于传入的pid参数值，这样就筛选出了属于指定父部门（id为0）下的所有子部门。
                .filter(dept -> dept != null && dept.getPid() == pid)

                // 3、构建部门树节点并递归添加子部门
                // 遍历前面筛选出来的每个子部门对象：宇通汽车租赁上海部（id为1）、宇通汽车租赁北京部（id为4）
                .forEach(dept -> {
                    // 首先创建一个新的Dept对象dept1，它将作为部门树中的一个节点来进行构建和处理。
                    Dept dept1 = new Dept();
                    // 将当前遍历到的部门对象dept的属性值复制到新创建的dept1对象中，除了一些在后续需要特殊处理的属性
                    // （比如这里的children属性，需要通过递归构建），这样dept1就拥有了和dept相同的基础部门信息。
                    BeanUtils.copyProperties(dept, dept1);
                    // 关键的递归调用部分
                    // 通过调用buildDeptTree方法自身，传入整个部门列表deptList以及当前部门对象dept的编号（通过dept.getId()获取），
                    // 目的是去查找并构建当前部门的子部门树结构，并将返回的子部门列表设置为dept1对象的children属性，
                    // 也就是在当前部门节点下添加它的子部门节点，从而逐步构建起完整的树形层次结构。
                    dept1.setChildren(buildDeptTree(deptList, dept.getId()));
                    // 最后，将构建好的包含子部门树的部门节点dept1添加到deptTree列表中，经过对所有筛选出来的子部门进行这样的处理后，
                    // deptTree列表就完整地构成了以传入的pid参数对应的部门为根节点的部门树结构。
                    deptTree.add(dept1);
                });
        return deptTree;
    }
}
